package com.yuedou.api.util;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import okhttp3.Response;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * @Description
 * @Author HanTao
 * @Data 2022/8/16 14:57
 **/
public class WxUtils {

    /**
     * 验证签名
     *
     * @param signature
     * @param timestamp
     * @param nonce
     * @return
     */
    public static boolean checkSignature(String signature, String timestamp,String nonce,String token) {

        // 将token、timestamp、nonce三个参数进行字典排序
        String[] arr = new String[] { token, timestamp, nonce };
        Arrays.sort(arr);

        // 将三个参数字符串拼接成一个字符串
        StringBuilder content = new StringBuilder();
        for (int i = 0; i < arr.length; i++) {
            content.append(arr[i]);
        }
        try {
            //获取加密工具
            MessageDigest md = MessageDigest.getInstance("SHA-1");
            // 对拼接好的字符串进行sha1加密
            byte[] digest = md.digest(content.toString().getBytes());
            String tmpStr = byteToStr(digest);
            //获得加密后的字符串与signature对比
            return tmpStr != null ? tmpStr.equals(signature.toUpperCase()): false;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return false;
    }

    private static String byteToStr(byte[] byteArray) {
        String strDigest = "";
        for (int i = 0; i < byteArray.length; i++) {
            strDigest += byteToHexStr(byteArray[i]);
        }
        return strDigest;
    }

    private static String byteToHexStr(byte mByte) {
        char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A',
                'B', 'C', 'D', 'E', 'F' };
        char[] tempArr = new char[2];
        tempArr[0] = Digit[(mByte >>> 4) & 0X0F];
        tempArr[1] = Digit[mByte & 0X0F];
        String s = new String(tempArr);
        return s;
    }

    /**
     * 微信网页授权 第二步 通过 code 换取网页授权access_token
     */
    public static Map<String, Object> wxGetAccessToken(String code, String appid, String secret) throws IOException {
        Map<String, Object> map = new HashMap<>(10);
        String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + appid + "&secret="
                + secret + "&code=" + code + "&grant_type=authorization_code";
        Response response = OkHttpClientUtil.getInstance().getData(url);
        if (response !=null && response.body()!=null){
            String res = response.body().string();
            cn.hutool.json.JSONObject jsonObject = JSONUtil.parseObj(res);

            // 用户唯一标识，请注意，在未关注公众号时，用户访问公众号的网页，也会产生一个用户和公众号唯一的OpenID
            String openid = jsonObject.containsKey("openid") ? jsonObject.getStr("openid") : "";
            // 网页授权接口调用凭证,注意：此access_token与基础支持的access_token不同
            String accessToken = jsonObject.containsKey("access_token") ? jsonObject.getStr("access_token") : "";
            // access_token接口调用凭证超时时间，单位（秒）
            int expiresIn = jsonObject.containsKey("expiresIn") ? jsonObject.getInt("expiresIn") : 0;
            // 用户刷新access_token
            String refreshToken = jsonObject.containsKey("refresh_token") ? jsonObject.getStr("refresh_token") : "";
            // 用户授权的作用域，使用逗号（,）分隔
            String scope = jsonObject.containsKey("scope") ? jsonObject.getStr("scope") : "";

            map.put("accessToken", accessToken);
            map.put("expiresIn", expiresIn);
            map.put("refreshToken", refreshToken);
            map.put("openid", openid);
            map.put("scope", scope);
        }
        return map;
    }

    /**
     * 刷新网页授权 access_token
     */
    public static Map<String, Object> wxRefreshAccessToken(String appid, String refreshToken) {
        Map<String, Object> map = new HashMap<>(10);
        String url = "https://api.weixin.qq.com/sns/oauth2/refresh_token";
        Map<String, Object> mapParam = new HashMap<>(4);
        mapParam.put("appid", appid);
        mapParam.put("grant_type", "refresh_token");
        mapParam.put("refresh_token", refreshToken);
        String returnParam = HttpUtil.httpClientPost(url, mapParam, "utf-8");
        JSONObject jsonObject = JSONObject.parseObject(returnParam);
        String errcode = jsonObject.getString("errcode");
        if (StringUtils.isNotEmpty(errcode)) {
            // 网页授权接口调用凭证,注意：此access_token与基础支持的access_token不同
            String accessToken = jsonObject.getString("access_token");
            // access_token接口调用凭证超时时间，单位（秒）
            String expiresIn = jsonObject.getString("expires_in");
            // 用户刷新access_token
            String refreshTokenNew = jsonObject.getString("refresh_token");
            // 用户唯一标识，请注意，在未关注公众号时，用户访问公众号的网页，也会产生一个用户和公众号唯一的OpenID
            String openid = jsonObject.getString("openid");
            // 用户授权的作用域，使用逗号（,）分隔
            String scope = jsonObject.getString("scope");
            map.put("accessToken", accessToken);
            map.put("expiresIn", expiresIn);
            map.put("refreshToken", refreshTokenNew);
            map.put("openid", openid);
            map.put("scope", scope);
        }
        return map;
    }

    /**
     * 获取用户信息
     */
    public static Map<String, Object> wxGetUserInfo(String accessToken, String openid) throws IOException {
        Map<String, Object> map = new HashMap<>(10);
        String url = "https://api.weixin.qq.com/sns/userinfo?access_token=" + accessToken + "&openid=" + openid + "&lang=zh_CN";
        Response response = OkHttpClientUtil.getInstance().getData(url);
        if (response != null && response.body() != null) {
            String data = response.body().string();
            cn.hutool.json.JSONObject jsonObject = JSONUtil.parseObj(data);
            openid = jsonObject.containsKey("openid") ? jsonObject.getStr("openid") : "";
            String unionid = jsonObject.containsKey("unionid") ? jsonObject.getStr("unionid") : "";
            int sex = jsonObject.containsKey("sex") ? jsonObject.getInt("sex") : 0;
            String nickname = jsonObject.containsKey("nickname") ? jsonObject.getStr("nickname") : "";
            String headImgUrl = jsonObject.containsKey("headimgurl") ? jsonObject.getStr("headimgurl") : "";
            map.put("openid", openid);
            map.put("unionid", unionid);
            map.put("sex", sex);
            map.put("nickname", nickname);
            map.put("headImgUrl", headImgUrl);
        }
        return map;
    }


}
